package cn.yh.nft.turbo.base.statemachine;

import cn.yh.nft.turbo.base.exception.BizException;
import com.google.common.base.Joiner;
import com.google.common.collect.Maps;

import java.util.Map;

import static cn.yh.nft.turbo.base.exception.BizErrorCode.STATE_MACHINE_TRANSITION_FAILED;

/**
 * @ClassName: BaseStateMachine
 * @Author: 草莓爱上啵啵
 *   定义一个泛型类 BaseStateMachine，它实现了 StateMachine 接口。
 *   STATE 和 EVENT 是泛型类型参数，分别表示状态和事件的类型。
 *   implements StateMachine<STATE, EVENT> 表示这个类实现了 StateMachine 接口，并且使用了泛型类型参数。
 */
public class BaseStateMachine<STATE, EVENT> implements StateMachine<STATE, EVENT>{

    /**
     * 定义一个私有成员变量 stateTransitions，它是一个 Map，键是 String 类型，值是 STATE 类型。
     * Maps.newHashMap() 用于创建一个新的 HashMap 实例（假设 Maps 是 Guava 库中的一个工具类，用于简化集合的创建）。
     * 这个 Map 用于存储状态转换的映射关系，其中键是由状态和事件组合成的字符串，值是目标状态。
     */
    private Map<String, STATE> stateTransitions = Maps.newHashMap();

    /**
     * 定义一个受保护的方法 putTransition，用于向 stateTransitions 中添加状态转换规则。
     * @param origin 当前状态
     * @param event 触发的事件
     * @param target 转换后的目标状态。
     */
    protected void putTransition(STATE origin, EVENT event, STATE target){
        /**
         * 使用 Joiner.on("_").join(origin, event) 将 origin 和 event 连接成一个字符串，用下划线 _ 分隔。
         * 将连接后的字符串作为键，target 作为值，存入 stateTransitions 中。
         * 这一行的作用是注册一个状态转换规则，即从 origin 状态经过 event 事件转换到 target 状态。
         */
        stateTransitions.put(Joiner.on("_").join(origin, event), target);
    }

    /**
     * 重写 StateMachine 接口中的 transition 方法。
     * @param state 当前状态
     * @param event 触发后的事件
     * @return 转换后的目标状态。
     */
    @Override
    public STATE transition(STATE state, EVENT event) {

        //使用 Joiner.on("_").join(state, event) 将 state 和 event 连接成一个字符串，用下划线 _ 分隔。
        //使用这个字符串作为键，从 stateTransitions 中获取对应的目标状态 target。
        STATE target = stateTransitions.get(Joiner.on("_").join(state, event));

        //检查 target 是否为 null，如果是，则表示没有找到对应的状态转换规则。
        //抛出一个 BizException 异常，表示状态机转换失败，并附带状态和事件的信息。
        //STATE_MACHINE_TRANSITION_FAILED 可能是表示状态机转换失败的错误代码。
        if (target == null) {
            throw new BizException("state = " + state + " , event = " + event, STATE_MACHINE_TRANSITION_FAILED);
        }

        return target;
    }
}
